/**
 * Created by CLAKE on 2016/10/26.
 */
import conf from '../config_select';

import {
    Calculate,
    GetElementXY,
    CloneObject,
    String2Hex,
    Extend,
    Storage
} from '../util/common';

export default class AreaSelect {
    constructor(cfg) {
        //全局配置
        this.initCFG = Extend(conf,cfg);
        this.cfg = CloneObject(this.initCFG);
        //主画布
        this.eml = document.getElementById(this.cfg.element);
        this.eml.oncontextmenu = ()=>{return false;};
        //初始化方法
        this._initPIXI();
        this._initFPS();
        this._initArea();
        this._initMove();
    }

    /**
     * 初始化PIXI工具
     * @private
     */
    _initPIXI() {
        this.width = this.eml.clientWidth;
        this.height = this.eml.clientHeight;
        // this.eml.style.width = this.width + 'px';
        // this.eml.style.height = this.height + 'px';
        this.renderer = new PIXI.autoDetectRenderer(this.width,this.height,{
            transparent:true,
            resolution: window.devicePixelRatio || 1,
            preserveDrawingBuffer:true
        });
        this.eml.appendChild(this.renderer.view);
        this.stage = new PIXI.Container();
        this.stage.x = 0;
        this.stage.y = 0;
    }

    /**
     * 初始化FPS显示文字
     * 配置文件内配置是否显示 fps:true
     * @private
     */
    _initFPS() {
        if (this.cfg.fps) {
            this.fps = new PIXI.Text('FPS: 0',{fontFamily:'Arial',fontSize:10,fill:0xff0000});
            this.stage.addChild(this.fps);
        } else {
            this.stage.removeChild(this.fps);
        }
    }

    _initArea() {
        this.data = [];
        this.scale = 1;
    }

    _initMove() {
        this.moved = false;
        this.scale = 1;
        this.isTouch = false;
        this.renderer.view.addEventListener('touchstart',(e)=>{
            this._evtMoveStart(this._formatEvent(e));
        },false);
        this.renderer.view.addEventListener('touchmove',(e)=>{
            this._evtMove(this._formatEvent(e));
        },false);
        this.renderer.view.addEventListener('touchend',(e)=>{
            this._evtMoveEnd(this._formatEvent(e));
        },false);
        this.renderer.view.addEventListener('mousedown',(e)=>{
            this._evtMoveStart(this._formatEvent(e));
        },false);
        this.renderer.view.addEventListener('mousemove',(e)=>{
            this._evtMove(this._formatEvent(e));
        },false);
        this.renderer.view.addEventListener('mouseup',(e)=>{
            this._evtMoveEnd(this._formatEvent(e));
        },false);
        this.renderer.view.addEventListener('mousewheel',(e)=>{
            var scroll = e.wheelDelta / 120 * .1;
            this.scale += scroll;
            this.scale = Math.max(.5,Math.min(this.scale,10));

            var w = this.stage.width,h=this.stage.height;
            var x = this.stage.x,y=this.stage.y;
            //中心放大
            this.stage.scale = new PIXI.Point(this.scale,this.scale);
            // this.stage.x = x- (this.stage.width-w)/2;
            // this.stage.y = y-(this.stage.height-h)/2;
            //原点放大
            this.stage.x = x - (e.offsetX - x) / w * (this.stage.width-w);
            this.stage.y = y - (e.offsetY - y) / h * (this.stage.height-h);

        },false);
    }

    _formatEvent(e) {
        var evt = {};
        if (e.type.indexOf('touch') !== -1) {
            this.isTouch = true;
            if (e.touches.length === 1) {
                evt.x = e.touches[0].clientX;
                evt.y = e.touches[0].clientY;
                this.zoom = false;
            } else if (e.touches.length >= 2) {
                this.zoom = true;
                evt.touchs = {
                    touch1:{x:e.touches[0].clientX,y:e.touches[0].clientY},
                    touch2:{x:e.touches[1].clientX,y:e.touches[1].clientY}
                }
            } else {
                this.zoom = false;
            }
        } else {
            this.isTouch = false;
            evt.x = e.clientX;
            evt.y = e.clientY;
        }
        return evt;
    }

    /**
     * 开始移动事件
     * @param e DOMEvent
     * @private
     */
    _evtMoveStart(e) {
        this.startPoint = {
            x:e.x,
            y:e.y,
            sx:this.stage.x,
            sy:this.stage.y,
            touchs: this.isTouch ? e.touchs : null
        };
        this.re_move = true;
    }

    /**
     * 移动中事件
     * @param e
     * @private
     */
    _evtMove(e) {
        var x,y;
        if (this.re_move && !this.zoom) {

            x = this.startPoint.sx + (e.x - this.startPoint.x);
            y = this.startPoint.sy + (e.y - this.startPoint.y);
            // x = x > 0 ? 0 : x ;
            // y = y > 0 ? 0 : y ;
            this.stage.x = x;
            this.stage.y = y;
            if (e.x != this.startPoint.x  || e.y != this.startPoint.y) {
                this.moved = true;
            }
        } else if (this.zoom) {
            var evt_scale = this._getZooms(this.startPoint.touchs,e.touchs,this.scale);
            var center_point = this._getCenterPoint(e.touchs);
            var w = this.stage.width,h=this.stage.height;
            x = this.stage.x;
            y = this.stage.y;
            this.stage.scale = new PIXI.Point(evt_scale,evt_scale);
            this.stage.x = x - (center_point.x - x) / w * (this.stage.width-w);
            this.stage.y = y - (center_point.y - y) / h * (this.stage.height-h);
        }
    }

    /**
     * 移动结束事件
     * @param e
     * @private
     */
    _evtMoveEnd(e) {
        this.re_move = false;
        this.moved = false;
        this.scale = this.stage.scale.x;
    }

    /**
     * 得到TOUCH的缩放率
     * @param sTouch 开始滑动的Touch集合
     * @param mTouch 滑动中的Touch集合
     * @param last 缩放结束后的缩放率
     * @returns {number}
     * @private
     */
    _getZooms(sTouch, mTouch, last) {
        // 计算放大倍数：首先计算出两点间X坐标和y坐标的距离(x坐标相减：x = touch1.x-touch2.x，得到X轴距离；y坐标相减：y = touch1.y-touch2.y，得到Y轴距离)
        // 这时，可得到一个直角三角形，通过勾股定理：Z^2 = X^2 + Y^2，得知两点间距离Z的值；同理，在移动的时候可以计算出移动的距离，移动的距离：原始距离 = 放大倍数。
        var zooms = function (touch) {
            var touch1 = touch.touch1, touch2 = touch.touch2;

            var x = touch1.x - (touch2 ? touch2.x : 0),
                y = touch1.y - (touch2 ? touch2.y : 0);
            return Math.sqrt((x * x) + (y * y));
        };
        return Math.max(.5, Math.min(last * (zooms(mTouch) / zooms(sTouch)), 10));
    }

    /**
     * 得到两点中心点
     * @param touchs
     * @returns {{x: number, y: number}}
     * @private
     */
    _getCenterPoint(touchs) {
        return {
            x : (touchs.touch1.x + touchs.touch2.x)/2,
            y : (touchs.touch1.y + touchs.touch2.y)/2
        };
    }

    /**
     * 画出座位图标
     * @param gs PIXI.Graphics
     * @param color HEX COLOR
     * @private
     */
    _buildIcon(gs,color) {
        gs.clear();
        gs.beginFill(color);
        // gs.lineStyle(1,0x000000);
        gs.moveTo(1,2);
        gs.lineTo(2,2);
        gs.lineTo(5,5);
        gs.lineTo(14,5);
        gs.lineTo(17,2);
        gs.lineTo(18,2);
        gs.lineTo(18,18);
        gs.lineTo(1,18);
        gs.lineTo(1,2);
        // gs.drawRect(0,0,this.cfg.rectWidth,this.cfg.rectHeight);
        gs.endFill();
    }

    /**
     * 画出座位选中勾
     * @param gs PIXI.Graphics
     * @private
     */
    _buildCheckIcon(gs) {
        gs.lineStyle(1,0xFFFFFF);
        gs.moveTo(5,10);
        gs.lineTo(9,14);
        gs.lineTo(15,8);
    }

    /**
     * 画出锁定的圈
     * @param gs
     * @private
     */
    _buildLocked(gs) {
        gs.lineStyle(1,0xFFFFFF);
        gs.moveTo(5,8);
        gs.lineTo(14,16);
        gs.moveTo(14,8);
        gs.lineTo(5,16);
    }

    /**
     * 生成内容
     */
    _render() {
        if (this.cfg.fps) {
            this.fps.text = 'FPS: ' +  this.ticker.FPS.toFixed(2);
        }
        this.renderer.render(this.stage);
    }

    _seatClickHandler = (e)=>{
        if (this.moved) return;
        var me = e.target;
        me.checked = !me.checked;
        if (me.checked) {
            this._buildIcon(me,0x99CC66);
            this._buildCheckIcon(me);
        } else {
            this._buildIcon(me,String2Hex(me.data.color));
        }
        if (this.clickCallback) {
            this.clickCallback(me.data,me.checked,this.stage.getChildIndex(me));
        }
    };

    /*********************************************************************
     * 公共方法
     * public functions
     */

    /**
     * 显示或关闭FPS
     * @param flag bool
     */
    showFPS(flag) {
        this.cfg.fps = flag;
        this._initFPS();
    }

    /***
     * 开始工作
     */
    start() {
        this.ticker = new PIXI.ticker.Ticker();
        this.ticker.add((currentTime)=>{
            this._render();
        });
        this.ticker.start();
    }

    setData(data,func) {
        if (!data instanceof Array) {
            return;
        }
        this.clickCallback = func;
        this.data = data;
        this.data.forEach((item,index)=>{
            var gs = new PIXI.Graphics();
            gs.x = (item.col - 1) * this.cfg.rectWidth;
            gs.y = (item.row - 1) * this.cfg.rectHeight;
            if (item.disabled) {
                this._buildIcon(gs,String2Hex(item.color));
                this._buildLocked(gs);
            } else {
                this._buildIcon(gs,String2Hex(item.color));
                gs.data = item;
                gs.checked = false;
                gs.interactive = true;
                gs.seat_index = index;
                gs.on('tap',this._seatClickHandler);
                gs.on('click',this._seatClickHandler);
            }
            this.stage.addChild(gs);
            gs = null;
        });
        this.scale = this.width / this.stage.width;
        this.stage.scale.set(this.scale,this.scale);
    }

    cancelCheck(seat_index) {
        var gs = this.stage.getChildAt(seat_index);
        gs.checked = false;
        gs.clear();
        this._buildIcon(gs,String2Hex(gs.data.color));
    }
}